{
 "cells": [
  {
   "cell_type": "code",
   "id": "initial_id",
   "metadata": {
    "collapsed": true,
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:35.217732Z",
     "start_time": "2025-03-02T10:15:35.215094Z"
    }
   },
   "source": [
    "import cv2\n",
    "import numpy as np"
   ],
   "outputs": [],
   "execution_count": 422
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:35.754552Z",
     "start_time": "2025-03-02T10:15:35.248310Z"
    }
   },
   "cell_type": "code",
   "source": [
    "image_path = \"dataset/image5.jpg\"\n",
    "image = cv2.imread(image_path)\n",
    "\n",
    "# 转换为灰度图像\n",
    "gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
    "\n",
    "# 将亮度过低的区域转换为黑色\n",
    "mask = gray_image < 150\n",
    "gray_image[mask] = 0\n",
    "\n",
    "# 应用高斯模糊\n",
    "blurred_image = cv2.GaussianBlur(gray_image, (5, 5), 3)\n",
    "\n",
    "cv2.imshow('origin',image)\n",
    "cv2.imshow('gray',gray_image)\n",
    "cv2.imshow('blurred',blurred_image)\n",
    "\n",
    "cv2.waitKey(0)  # 按任意键退出\n",
    "cv2.destroyAllWindows()"
   ],
   "id": "7ac269df2619e9eb",
   "outputs": [],
   "execution_count": 423
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:35.982751Z",
     "start_time": "2025-03-02T10:15:35.771858Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# Canny 边缘检测\n",
    "edges = cv2.Canny(gray_image, 180, 255)\n",
    "edges_blurred = cv2.Canny(blurred_image, 180, 255)\n",
    "\n",
    "cv2.imshow('edge_origin',edges)\n",
    "cv2.imshow('edge_blurred',edges_blurred)\n",
    "\n",
    "cv2.waitKey(0)  # 按任意键退出\n",
    "cv2.destroyAllWindows()"
   ],
   "id": "645802118666760f",
   "outputs": [],
   "execution_count": 424
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:36.013981Z",
     "start_time": "2025-03-02T10:15:36.009501Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 定义感兴趣区域（ROI）\n",
    "def region_of_interest(image):\n",
    "    height = image.shape[0]\n",
    "    width = image.shape[1]\n",
    "\n",
    "    # 定义一个四边形区域\n",
    "    mask = np.zeros_like(image)\n",
    "    polygon = np.array([[\n",
    "        (0, height),\n",
    "        (0, height *2/3),\n",
    "        (width *1/3, height /2),\n",
    "        (width *2/3, height /2),\n",
    "        (width, height *2/3),\n",
    "        (width, height)\n",
    "    ]], np.int32)\n",
    "\n",
    "    cv2.fillPoly(mask, polygon, (255,255,255))\n",
    "    masked_image = cv2.bitwise_and(image, mask)\n",
    "    return masked_image"
   ],
   "id": "4f699fc9212545ab",
   "outputs": [],
   "execution_count": 425
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:36.218559Z",
     "start_time": "2025-03-02T10:15:36.045860Z"
    }
   },
   "cell_type": "code",
   "source": [
    "masked = region_of_interest(image)\n",
    "cv2.imshow('masked', masked)\n",
    "cv2.imshow('origin', image)\n",
    "\n",
    "cv2.waitKey(0)  # 按任意键退出\n",
    "cv2.destroyAllWindows()"
   ],
   "id": "97a0c9042ec723d7",
   "outputs": [],
   "execution_count": 426
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:36.260523Z",
     "start_time": "2025-03-02T10:15:36.256806Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 计算直线的斜率\n",
    "def calculate_slope(line):\n",
    "    x_1, y_1, x_2, y_2 = line[0]\n",
    "    if x_2 - x_1 != 0:\n",
    "        return (y_2 - y_1) / (x_2 - x_1)\n",
    "    else:\n",
    "        return np.inf"
   ],
   "id": "10f8d6fc7161cf84",
   "outputs": [],
   "execution_count": 427
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:36.786062Z",
     "start_time": "2025-03-02T10:15:36.309218Z"
    }
   },
   "cell_type": "code",
   "source": [
    "masked_edges = region_of_interest(edges_blurred)\n",
    "cv2.imshow('masked_edge',masked_edges)\n",
    "\n",
    "cv2.waitKey(0)  # 按任意键退出\n",
    "cv2.destroyAllWindows()"
   ],
   "id": "6be5198991a7358d",
   "outputs": [],
   "execution_count": 428
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:36.826220Z",
     "start_time": "2025-03-02T10:15:36.820079Z"
    }
   },
   "cell_type": "code",
   "source": [
    "def detect_roadline(masked_edges):\n",
    "    global image\n",
    "    h = masked_edges.shape[0]/20\n",
    "    # 霍夫变换检测车道线\n",
    "    lines = cv2.HoughLinesP(masked_edges, 1, np.pi / 180, threshold=50, minLineLength=h, maxLineGap=h/4)\n",
    "\n",
    "    # 绘制检测到的车道线\n",
    "    line_image = np.zeros_like(image)\n",
    "    if lines is not None:\n",
    "        for line in lines:\n",
    "            x1, y1, x2, y2 = line[0]\n",
    "            k = calculate_slope(line)\n",
    "            if 10 >= k >= 0.5 or -10 <= k <= -0.5:  # 过滤斜率不正常的直线（接近水平或垂直）\n",
    "                cv2.line(line_image, (x1, y1), (x2, y2), (0, 255, 0), 5)\n",
    "\n",
    "    # 合并原图和车道线\n",
    "    res_image = cv2.addWeighted(image, 0.8, line_image, 1, 0)\n",
    "    return res_image"
   ],
   "id": "7a83aef70b446999",
   "outputs": [],
   "execution_count": 429
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:37.183048Z",
     "start_time": "2025-03-02T10:15:36.860763Z"
    }
   },
   "cell_type": "code",
   "source": [
    "final_image = detect_roadline(masked_edges)\n",
    "# 显示结果\n",
    "cv2.imshow('Lane Detection', final_image)\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "id": "867b919b2cdf2ea4",
   "outputs": [],
   "execution_count": 430
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 交通标志识别",
   "id": "70086ec188aeef81"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:37.218911Z",
     "start_time": "2025-03-02T10:15:37.214277Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 遮盖下半部分区域\n",
    "def lower_mask(image):\n",
    "    height = image.shape[0]\n",
    "    width = image.shape[1]\n",
    "\n",
    "    # 定义一个四边形区域\n",
    "    mask = np.zeros_like(image)\n",
    "    polygon = np.array([[\n",
    "        (0, 0),\n",
    "        (0, height/2),\n",
    "        (width, height/2),\n",
    "        (width, 0)\n",
    "    ]], np.int32)\n",
    "\n",
    "    cv2.fillPoly(mask, polygon, (255,255,255))\n",
    "    masked_image = cv2.bitwise_and(image, mask)\n",
    "    return masked_image"
   ],
   "id": "4e408de72954e8fb",
   "outputs": [],
   "execution_count": 431
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:45.894267Z",
     "start_time": "2025-03-02T10:15:37.230437Z"
    }
   },
   "cell_type": "code",
   "source": [
    "wmasked = lower_mask(image)\n",
    "cv2.imshow('masked', masked)\n",
    "cv2.imshow('origin', image)\n",
    "\n",
    "cv2.waitKey(0)  # 按任意键退出\n",
    "cv2.destroyAllWindows()"
   ],
   "id": "3585e33d342ba8c2",
   "outputs": [],
   "execution_count": 432
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:15:45.926983Z",
     "start_time": "2025-03-02T10:15:45.923854Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 提取图像蓝色部分\n",
    "def extract_blue_region(image):\n",
    "    # 将 BGR 图像转换为 HSV 图像\n",
    "    hsv_img = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)\n",
    "\n",
    "    # 设置蓝色的 HSV 范围\n",
    "    lower_blue = np.array([100, 150, 100])   # 蓝色的低范围\n",
    "    upper_blue = np.array([130, 255, 200])  # 蓝色的高范围\n",
    "\n",
    "    # 使用 inRange() 函数提取蓝色区域\n",
    "    blue_mask = cv2.inRange(hsv_img, lower_blue, upper_blue)\n",
    "\n",
    "    # 根据掩膜提取蓝色区域\n",
    "    blue_region = cv2.bitwise_and(image, image, mask=blue_mask)\n",
    "\n",
    "    return blue_region"
   ],
   "id": "b12b01f3d1106c3d",
   "outputs": [],
   "execution_count": 433
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:17:06.563898Z",
     "start_time": "2025-03-02T10:15:45.957988Z"
    }
   },
   "cell_type": "code",
   "source": [
    "masked_img = lower_mask(image)\n",
    "blue_region = extract_blue_region(masked_img)\n",
    "\n",
    "cv2.imshow('masked_region',masked_img)\n",
    "cv2.imshow('blue_region',blue_region)\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "id": "fed97611d2983a19",
   "outputs": [],
   "execution_count": 434
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:18:08.613959Z",
     "start_time": "2025-03-02T10:17:06.598074Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 高斯模糊\n",
    "blurred = cv2.blur(blue_region, (9,9))\n",
    "cv2.imshow('blurred',blurred)\n",
    "\n",
    "# 二值化\n",
    "ret,binary = cv2.threshold(blurred, 50, 255, cv2.THRESH_BINARY)\n",
    "cv2.imshow('blurred binary',binary)\n",
    "\n",
    "# 使区域闭合无空隙\n",
    "kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 7))\n",
    "closed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel)\n",
    "cv2.imshow('closed',closed)\n",
    "\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "id": "c917ea70cba71f93",
   "outputs": [],
   "execution_count": 435
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-02T10:18:19.990195Z",
     "start_time": "2025-03-02T10:18:08.662024Z"
    }
   },
   "cell_type": "code",
   "source": [
    "gray_closed = cv2.cvtColor(closed, cv2.COLOR_BGR2GRAY)\n",
    "contours, _ = cv2.findContours(gray_closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)\n",
    "\n",
    "# 遍历所有轮廓\n",
    "for contour in contours:\n",
    "    # 计算最小外接矩形\n",
    "    rect = cv2.minAreaRect(contour)\n",
    "    # 获取矩形的角点\n",
    "    box = cv2.boxPoints(rect)\n",
    "    box = np.array(box, dtype=np.int32)  # 转换为整数\n",
    "\n",
    "    # 在原图像上绘制最小外接矩形\n",
    "    cv2.drawContours(image, [box], 0, (0, 255, 0), 3)\n",
    "\n",
    "cv2.imshow('signal_detect', image)\n",
    "cv2.waitKey(0)\n",
    "cv2.destroyAllWindows()"
   ],
   "id": "6dc0490a5d0e823d",
   "outputs": [],
   "execution_count": 436
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
